package cc.picc.quota;

import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author lijinting01
 *
 * @param <E>
 */
public abstract class AbstractQuotaBucket<E> implements QuotaBucket<E> {

	private int capacity;

	private Queue<E> queue;

	/**
	 * @param capacity
	 *            边界容量
	 */
	public AbstractQuotaBucket(final int capacity) {
		queue = new LinkedBlockingQueue<>(capacity);
		this.capacity = capacity;
	}

	@Override
	public Optional<E> pop() {
		return Optional.ofNullable(queue.poll());
	}

	@Override
	public int fill(final int number) {
		int counter = 0;
		for (int i = 0; i < number; i += 1) {
			counter += fillSingle();
		}
		return counter;
	}

	/*
	 * 速度很慢，慎用。
	 * 
	 * @see cc.picc.quota.QuotaBucket#size()
	 */
	@Override
	public int size() {
		return queue.size();
	}

	@Override
	public int capacity() {
		return capacity;
	}

	/**
	 * 制作令牌的方法
	 * 
	 * @return
	 */
	protected abstract QuotaProvider<E> defineQuotaProvider();

	/**
	 * 往桶中填充1个令牌
	 * 
	 * @return
	 */
	private int fillSingle() {
		if (queue.offer(defineQuotaProvider().provide()))
			return 1;// 成功添加就返回1
		return 0;
	}

}
